package vip.xiaonuo.bi.core.datasource.common.client;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.google.common.collect.Lists;
import org.springframework.stereotype.Component;
import vip.xiaonuo.bi.core.datasource.common.AbstractDataSourceConfig;
import vip.xiaonuo.bi.core.datasource.config.SqlQueryConig;
import vip.xiaonuo.bi.core.datasource.factory.AbstractConectionFactory;
import vip.xiaonuo.bi.core.datasource.util.DButils;
import vip.xiaonuo.bi.modular.datasource.dto.ColunmDto;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 关系型数据库 mysql orancle 默认对象
 *
 * @author 顾育司
 * @date 2023/12/15 12:09
 */
@Component
public abstract class AbstractRdbmsClient implements DataSourceClient {

    protected AbstractConectionFactory connectionFactory = getConectionFactory();

    protected abstract AbstractConectionFactory getConectionFactory();

    @Override
    public Boolean testConnection(AbstractDataSourceConfig config) throws Exception {
        System.out.println(JSONObject.toJSONString(config));

        System.out.println("测试连接！！！");
        connectionFactory.testConnection(config);
        return null;
    }

    @Override
    public Connection getConnection(AbstractDataSourceConfig config) throws Exception {
        return connectionFactory.getConnection(config);
    }

    /**
     *
     * @param dataSourceConfig
     * @param queryConig
     * @return
     */
    @Override
    public List<String> getTableList(AbstractDataSourceConfig dataSourceConfig, SqlQueryConig queryConig) {
        ResultSet rs = null;
        Connection connection = null;
        try {

            connection = getConnection(dataSourceConfig);
            // 获取元数据信息
            DatabaseMetaData metaData = connection.getMetaData();
            // 定义结果集
            List<String> list = new ArrayList<>();
            // 获取元数据表信息
            rs = metaData.getTables(queryConig.getSchema(), queryConig.getSchema(), "%", new String[]{"TABLE"});
            // 便利结果集
            while (rs.next()) {
                // 取出表明
                String tableName = rs.getString("TABLE_NAME");
                if (!StrUtil.startWithIgnoreCase(tableName, "ACT_")) {
                    list.add(tableName);
//                    String remarks = rs.getString("REMARKS"); 表注释
                }
            }
            return list;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            // 关闭
            connectionFactory.close(connection, null, rs);
        }

    }

    /**
     * 获取关系型数据类型的 表的列字段
     * @param dataSourceConfig
     * @param queryConig
     * @return
     */
    public  List<ColunmDto> getcolumList(AbstractDataSourceConfig dataSourceConfig, SqlQueryConig queryConig) {
        Connection connection = null;
        Statement statement = null;
        ResultSet rs = null;
        List<ColunmDto> result = new ArrayList<>();
        try {

            // 获取执行sql语句  select * from table where 1=2;
            String queryColumnSql = DButils.getQueryColumnSql(queryConig.getTable());
            // 获取元数据信息
//            connection = dataSourceConfig.getConnection();
            connection = getConnection(dataSourceConfig);
            // 获取预编译
            statement = connection.createStatement();
            // 获取执行结果集
            rs = statement.executeQuery(queryColumnSql);

            // 1 获取结果集元数据 ==》名称和类型
            ResultSetMetaData resultSetMetaData =  rs.getMetaData();
            for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
                // 挨个取出列名称
                result.add(ColunmDto.builder()
                        // 取出字段名称
                        .name(resultSetMetaData.getColumnName(i))
                        // 取出字段类型
                                .type(resultSetMetaData.getColumnTypeName(i).toLowerCase())
                        .build());
            }

            // 2 获取结果集元数据 ==》注释
            Map<String, String> columnComments = getColumnComments(dataSourceConfig, queryConig);
            //前提 需要具体类型实现获取字段注释
            if (columnComments!= null && columnComments.size() > 0){
                result.stream().forEach(item->{
                    // 插入注释
                    item.setComment(columnComments.get(item.getName()));
                });
            }
            return result;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            // 关闭
            connectionFactory.close(connection, statement, rs);
        }
    }

    /**
     * 获取字段注释 需要每个具体的数据源类型去继承才有字段注释
     * @param dataSourceConfig
     * @param queryConig
     * @return
     */
    protected Map<String, String> getColumnComments(AbstractDataSourceConfig dataSourceConfig, SqlQueryConig queryConig) {
        return null;
    }


    /**
     * 获得关系型等sql能够执行的表的预览数据
     * @param dataSourceConfig
     * @param queryConig
     * @return
     */
    @Override
    public List<List<String>> getPreview(AbstractDataSourceConfig dataSourceConfig, SqlQueryConig queryConig) {
        // 获取默认的
        List<List<String>> result = new ArrayList<>();
        // 获取连接
        Connection connection = null;
        // 获取预编译对象
        Statement statement = null;
        // 获取结果集
        ResultSet rs = null;

        try {
            // 获取表的预览数据
            String queryColumnSql =null;

            // 获取连接对象
            connection = getConnection(dataSourceConfig);
            // 获取预编译对象
            statement = connection.createStatement();

            // 是否是sql执行
            if(queryConig.getSql()!=null){
                // 获取执行sql语句  select * from table;
                queryColumnSql = queryConig.getSql();
            }else{
                // 获取执行sql语句  select * from table;
                queryColumnSql = DButils.getQueryTableSql(queryConig.getTable());
            }

            // 预览数据限制
            if(ObjectUtils.isNotEmpty(queryConig.getLimit())){
                // 设置最大返回行数
                statement.setMaxRows(queryConig.getLimit());
            }

            // 获取执行结果集
            rs = statement.executeQuery(queryColumnSql);
            // 获取结果集的元数据的列信息

            // 1.获取列信息
            ResultSetMetaData rsmd = rs.getMetaData();
            //存储字段信息
            List<String> metaDataList = Lists.newArrayList();
            //字段数量
            int len = rsmd.getColumnCount();
            for (int i = 0; i < len; i++) {
                //获取字段名
                metaDataList.add(rsmd.getColumnLabel(i + 1));
            }
            // 添加到结果集
            result.add(metaDataList);
            // 2.获取表数据
            while (rs.next()) {
                // 获取每行数据
                List<String> row = Lists.newArrayList();
                // 获取每行每列的值
                for (int i = 0; i < len; i++) {
                    // 获取每行每列的值
                    Object value = rs.getObject(i + 1);
                    // 添加到每行数据
                    row.add(value==null?null:String.valueOf(value));
                }
                // 添加到结果集
                result.add(row);
            }

            return result;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            // 关闭
            connectionFactory.close(connection, statement, rs);
        }
    }

}
